/*
 * Copyright (c) 2025 Li Auto Inc. and its affiliates
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SRC_CPP_RTPS_TRANSPORT_IPCTRANSPORTINTERFACE_H_
#define SRC_CPP_RTPS_TRANSPORT_IPCTRANSPORTINTERFACE_H_

#include <transport/TransportInterface.h>

#include <thread>
#include <vector>

#include <transport/IPCTransportDescriptor.h>

#include <ertps/utils/LocatorAlias.h>

namespace vbs {
namespace transport {

class IPCChannelResource;

class IPCTransport : public TransportInterface {
    friend class IPCSenderResource;

 public:
    IPCTransport(const IPCTransportDescriptor& descriptor);

    ~IPCTransport() override;

    bool init() override;

    /**
     * Blocking Send through the specified channel. In both modes, using a localLocator of 0.0.0.0
     * will send through all whitelisted interfaces provided the channel is open.
     * @param send_buffer Slice into the raw data to send.
     * @param send_buffer_size Size of the raw data. It will be used as a bounds check for the
     * previous argument. It must not exceed the send_buffer_size fed to this class during
     * construction.
     */
    bool send(unsigned char* send_buffer, uint32_t send_buffer_size,
              vbsutil::xmlparser::LocatorsIterator* destination_locators_begin,
              vbsutil::xmlparser::LocatorsIterator* destination_locators_end);

    const IPCTransportDescriptor* configuration() const { return &configuration_; }

    /**
     * Starts listening on the specified port, and if the specified address is in the
     * multicast range, it joins the specified multicast group,
     */
    bool OpenInputChannel(const Locator&, std::shared_ptr<ReceiverResource>, uint32_t) override;

    //! Removes the listening socket for the specified port.
    bool CloseInputChannel(const Locator&) override;

    //! Checks whether there are open and bound sockets for the given port.
    bool IsInputChannelOpen(const Locator&) const override;

    //! Reports whether Locators correspond to the same port.
    bool DoInputLocatorsMatch(const Locator&, const Locator&) const override;

    //! Checks for TCP kinds.
    bool IsLocatorSupported(const Locator&) const override;

    //! Opens a socket on the given address and port (as long as they are white listed).
    bool OpenOutputChannel(SendResourceList& sender_resource_list, const Locator&) override;

#if 0
    /**
     * Converts a given remote locator (that is, a locator referring to a remote
     * destination) to the main local locator whose channel can write to that
     * destination. In this case it will return a 0.0.0.0 address on that port.
     */
    Locator RemoteToMainLocal(const Locator&) const override;

    /**
     * Transforms a remote locator into a locator optimized for local communications.
     *
     * If the remote locator corresponds to one of the local interfaces, it is converted
     * to the corresponding local address.
     *
     * @param [in]  remote_locator Locator to be converted.
     * @param [out] result_locator Converted locator.
     *
     * @return false if the input locator is not supported/allowed by this transport, true
     * otherwise.
     */
    bool transform_remote_locator(const Locator& remote_locator, Locator& result_locator) const override;

    LocatorList NormalizeLocator(const Locator& locator) override;

    bool is_local_locator(const Locator& locator) const override;
#endif
    TransportDescriptorInterface* get_configuration() override { return &configuration_; }

#if 0
    void AddDefaultOutputLocator(LocatorList& defaultList) override;

    bool getDefaultMetatrafficMulticastLocators(LocatorList& locators,
                                                uint32_t metatraffic_multicast_port) const override;

    bool getDefaultMetatrafficUnicastLocators(LocatorList& locators, uint32_t metatraffic_unicast_port) const override;

    bool getDefaultUnicastLocators(LocatorList& locators, uint32_t unicast_port) const override;
   
    bool select_multicast() const override {return false;}

    bool fillMetatrafficMulticastLocator(Locator& locator, uint32_t metatraffic_multicast_port) const override;

    bool fillMetatrafficUnicastLocator(Locator& locator, uint32_t metatraffic_unicast_port) const override;

    bool configureInitialPeerLocator(Locator& locator, const vbsutil::xmlparser::PortParameters& port_params,
                                     uint32_t domainId, LocatorList& list) const override;

    bool fillUnicastLocator(Locator& locator, uint32_t well_known_port) const override;
#endif
    bool is_locator_allowed(const Locator&) const override;

    uint32_t max_recv_buffer_size() const override { return configuration_.max_message_size(); }

 protected:
    //friend class IPCChannelResource;

    bool bInit_ = false;
    bool bSendResourceExist_ = false;
    IPCTransportDescriptor configuration_;

    IPCChannelResource* channel_resource_ = nullptr;
};

}  // namespace transport
}  // namespace vbs

#endif  // SRC_CPP_RTPS_TRANSPORT_IPCTRANSPORTINTERFACE_H_
